/*
 * @Descripttion:  业务数据加解密公用方法
 * @version: 1.0
 * @Author: zengying
 * @Date: 2020-04-14 16:10:38
 * @LastEditors: zengying
 * @LastEditTime: 2021-05-10 15:31:12
 */
"use strict";

import XxteaJs from "../utils/Xxteas.js";


class DecodeFLow {
  constructor(privateKey, showStar = false, bEncode = false) {
    this._keyString = privateKey;
    this._showStar = showStar;
    this._bEncode = bEncode;
  }
  static init(privateKey) {
    const res = new DecodeFLow(privateKey);
    return res;
  }
  handler_decode(target, bEncode = false) {
    if (isUndef(target) || !isObject(target)) return target;

    const _copy = deepClone(target);
    const tKey = this._keyString;

    // 进行整体解密
    if (typeof _copy === "string") return this.decode(_copy);
    // 部分加解密
    decode_djsq(_copy, tKey, bEncode);
    const objMethods = {
      qlrxx: decode_qlrxx,
      tsgl: decode_tsgl,
      xgzxx: decode_xgzxx,
      jfxx: decode_jfxx,
      cfxx: decode_cfxx,
      dyxxList: decode_dyxxList
    };

    Object.keys(objMethods).forEach(function (key) {
      _copy[key] && objMethods[key](_copy[key], tKey, bEncode);
    });
    return _copy;
    // tip("_copy", _copy);
    // tip("target", target);
  }
  // 兼容原写法
  decode(str, bEncode) {
    if (!str) return str;
    return (bEncode ? encodeStr : decodeStr)(this._keyString)(str);
  }
}

// 加解密业务流最外层数据
export function decode_djsq(target, tKey, bEncode) {
  if (isUndef(target) || !isObject(target)) return target;
  const keys = [
    "sqrmc",
    "sqrsfzh",
    "sqrdhhm",
    "sjr",
    "sjrdhhm",
    "sjdz",
    "qlrmc",
    "fwzl",
    "tzrxm",
    "tzrdh"
  ];
  decode_json(keys, target, tKey, bEncode);
  return target;
}

export function decode_qlrxx(target, tKey, bEncode) {
  if (isUndef(target) || !isObject(target)) return target;

  const familyKeys = ["qlr", "ywr", 'dyr', 'dyqr'];
  Object.keys(target).forEach(key => {
    const v = target[key];
    if (isUndef(v) || !isArray(v)) {
      return v;
    }

    decode_qlr(v, tKey, bEncode);
    if (familyKeys.includes(key)) {
      decode_family(v, tKey, bEncode);
    }
  });
}

export function decode_dyxxList(target, tKey, bEncode) {
  if (isUndef(target) || !isObject(target)) return target;

  const objMethods = {
    qlrxx: decode_qlrxx
  };
  return (function () {
    target.forEach(v => {
      return Object.keys(objMethods).forEach(function (key) {
        return v[key] && objMethods[key](v[key], tKey, bEncode);
      });
    });
  })();
}

export function decode_tsgl(target, tKey, bEncode) {
  if (isUndef(target) || !isArray(target)) return target;

  const keys = ["zl", "qlrmc", "qlrzjh"];
  return (function () {
    return target.forEach(v => {
      return decode_json(keys, v, tKey, bEncode);
    });
  })();
}

export function decode_xgzxx(target, tKey, bEncode) {
  if (isUndef(target) || !isArray(target)) return target;

  const keys = ["zl", "qlrmc", "qlrzjh"];
  return (function () {
    return target.forEach(v => {
      return decode_json(keys, v, tKey, bEncode);
    });
  })();
}

export function decode_cfxx(target, tKey, bEncode) {
  if (isUndef(target) || !isObject(target)) return target;

  const keys = ["sqzxr", "bzxr", "lxdh"];
  return (function () {
    decode_json(keys, target, tKey, bEncode);
  })();
}

export function decode_jfxx(target, tKey, bEncode) {
  if (isUndef(target) || !isObject(target)) return target;

  const keys = ["lxdh"];
  return (function () {
    decode_json(keys, target, tKey, bEncode);
  })();
}

export function decode_qlr(target, tKey = this._keyString, bEncode = this._bEncode) {
  if (isUndef(target) || !isArray(target)) return target;
  const keys = ["name", "zjhm", "dh", "frdbrxm", "frdbzjh", "frdbdhhm", "blrxm"];
  return (function () {
    return target.forEach(v => {
      v.dz = "";
      return decode_json(keys, v, tKey, bEncode);
    });
  })();
}

export function decode_family(target, tKey, bEncode) {
  if (isUndef(target) || !isArray(target)) return target;
  const keys = ["name", "zjhm"];
  return (function () {
    return target.forEach(v => {
      const {
        family = []
      } = v;
      if (isUndef(family) || !isArray(family)) return family;
      family.forEach(i => {
        return decode_json(keys, i, tKey, bEncode);
      });
    });
  })();
}

//#region commonMethod
export const decode_json = (keys, jsonObj, tKey = this._keyString, bEncode = this._bEncode) => {
  return (bEncode ? encodeJsonObj : decodeJsonObj)(keys, jsonObj, tKey || this._keyString);
};

export function isUndef(v) {
  return v === undefined || v === null;
}

export function isObject(v) {
  return v !== null && typeof v === "object";
}

export function isArray(v) {
  return v !== null && Array.isArray(v);
}

const {
  log,
  error
} = console;

export const warn = function (msg, vm) {
  error("[warn]: " + msg, vm);
};

export const tip = function (msg, vm) {
  log("[log]: " + msg, vm);
};

// 加密
export const encodeStr = tKey => {
  return function (str, xt = new XxteaJs.Xxtea(tKey)) {
    if (!str) return str;
    return xt.xxtea_encrypt(str);
  };
};

// 解密
export const decodeStr = tKey => {
  return function (str, xt = new XxteaJs.Xxtea(tKey)) {
    if (!str) return str;
    return xt.xxtea_decrypt(str);
  };
};

// 对json对象进行解密
export function decodeJsonObj(keys, jsonObj = {}, tKey = "") {
  if (isUndef(keys) || !isArray(keys)) return warn("keys type error");
  for (let i = keys.length - 1; i > -1; i--) {
    const key = keys[i];
    jsonObj[key] = decodeStr(tKey)(jsonObj[key]);
  }
  return jsonObj;
}

// 对json对象进行加密
export function encodeJsonObj(keys, jsonObj = {}, tKey = "") {
  if (isUndef(keys) || !isArray(keys)) return warn("keys type error");
  for (let i = keys.length - 1; i > -1; i--) {
    const key = keys[i];
    jsonObj[key] = encodeStr(tKey)(jsonObj[key]);
  }
  return jsonObj;
}

/**
 * @description deepClone
 * @author zengying
 * @date 2021/04/21 13:39:47
 * @param {object} source
 * @returns {object}
 */
export function deepClone(source) {
  if (!source && typeof source !== "object") {
    throw new Error("error arguments", "deepClone");
  }

  var targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach(function (keys) {
    if (source[keys] && typeof source[keys] === "object") {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
}

export const deepObjectMerge = (FirstOBJ, SecondOBJ) => {
  Object.keys(SecondOBJ).forEach(Element => {
    if (Element in FirstOBJ) {
      FirstOBJ[Element] = JSON.parse(JSON.stringify(SecondOBJ[Element]));
    }
  });
  return FirstOBJ;
};
//#endregion

DecodeFLow.prototype.decode_djsq = decode_djsq;
DecodeFLow.prototype.decode_tsgl = decode_tsgl;
DecodeFLow.prototype.decode_xgzxx = decode_xgzxx;
DecodeFLow.prototype.decode_jfxx = decode_jfxx;
DecodeFLow.prototype.decode_cfxx = decode_cfxx;
DecodeFLow.prototype.decode_qlrxx = decode_qlrxx;
DecodeFLow.prototype.decode_qlr = decode_qlr;
DecodeFLow.prototype.decode_family = decode_family;
DecodeFLow.prototype.decode_json = decode_json;

export default DecodeFLow;
